package com.hsxxherp.simplify.framework.algorithm;

import org.bouncycastle.crypto.engines.SM4Engine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.encoders.Hex;

import java.security.Security;

public class SM4Utils {

    static {
        // 添加 Bouncy Castle 安全提供者
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    }

    private static final int BLOCK_SIZE = 16; // SM4 块大小为 128 位（16 字节）

    private SM4Utils() {
        // 私有构造函数，防止实例化
    }

    /**
     * ECB 模式加密
     * @param plaintext 明文数据
     * @param key 密钥，长度为 16 字节
     * @return 加密后的十六进制字符串
     * @throws Exception 加密过程中可能抛出的异常
     */
    public static String encryptECB(byte[] plaintext, byte[] key) throws Exception {
        SM4Engine engine = new SM4Engine();
        PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(engine);
        cipher.init(true, new KeyParameter(key));

        byte[] output = new byte[cipher.getOutputSize(plaintext.length)];
        int length = cipher.processBytes(plaintext, 0, plaintext.length, output, 0);
        cipher.doFinal(output, length);

        return Hex.toHexString(output);
    }

    /**
     * ECB 模式解密
     * @param ciphertext 加密后的十六进制字符串
     * @param key 密钥，长度为 16 字节
     * @return 解密后的明文数据
     * @throws Exception 解密过程中可能抛出的异常
     */
    public static byte[] decryptECB(String ciphertext, byte[] key) throws Exception {
        SM4Engine engine = new SM4Engine();
        PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(engine);
        cipher.init(false, new KeyParameter(key));

        byte[] input = Hex.decode(ciphertext);
        byte[] output = new byte[cipher.getOutputSize(input.length)];
        int length = cipher.processBytes(input, 0, input.length, output, 0);
        cipher.doFinal(output, length);

        return output;
    }

    /**
     * CBC 模式加密
     * @param plaintext 明文数据
     * @param key 密钥，长度为 16 字节
     * @param iv 初始化向量，长度为 16 字节
     * @return 加密后的十六进制字符串
     * @throws Exception 加密过程中可能抛出的异常
     */
    public static String encryptCBC(byte[] plaintext, byte[] key, byte[] iv) throws Exception {
        CBCBlockCipher blockCipher = new CBCBlockCipher(new SM4Engine());
        PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher);
        cipher.init(true, new ParametersWithIV(new KeyParameter(key), iv));

        byte[] output = new byte[cipher.getOutputSize(plaintext.length)];
        int length = cipher.processBytes(plaintext, 0, plaintext.length, output, 0);
        cipher.doFinal(output, length);

        return Hex.toHexString(output);
    }

    /**
     * CBC 模式解密
     * @param ciphertext 加密后的十六进制字符串
     * @param key 密钥，长度为 16 字节
     * @param iv 初始化向量，长度为 16 字节
     * @return 解密后的明文数据
     * @throws Exception 解密过程中可能抛出的异常
     */
    public static byte[] decryptCBC(String ciphertext, byte[] key, byte[] iv) throws Exception {
        CBCBlockCipher blockCipher = new CBCBlockCipher(new SM4Engine());
        PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher);
        cipher.init(false, new ParametersWithIV(new KeyParameter(key), iv));

        byte[] input = Hex.decode(ciphertext);
        byte[] output = new byte[cipher.getOutputSize(input.length)];
        int length = cipher.processBytes(input, 0, input.length, output, 0);
        cipher.doFinal(output, length);

        return output;
    }
}